
#pragma once
#include "util.hpp"
#include "hotManger.hpp"
#include <thread>
#include <unordered_map>
#include <memory>
namespace Cloud
{
    struct UserNode
    {
        UserNode():username(),password(),backupPath(),compressPath(),data(nullptr),hot(nullptr),t1(nullptr){}
        UserNode(const std::string &name, const std::string &pswd) : password(pswd), username(name), backupPath(Config::getInstance().backupFilePath() + username + "/"), compressPath(Config::getInstance().compressFilePath() + username + "/"), data(new DataManger(username + "Data")), hot(new HotManger(data.get(), backupPath, compressPath))
        ,t1(new std::thread(*(hot.get)()))
        {
            t1->detach();
        }
        std::string username;
        std::string password;
        std::string backupPath;
        std::string compressPath;
        std::shared_ptr<DataManger> data;
        std::shared_ptr<HotManger> hot;
        std::shared_ptr<std::thread> t1;
    };
    class UserManger
    {
    public:
        bool insert(const UserNode &e)
        {
            _shmux.lock();
            _table[e.username] = e;
            // 插入数据库
            std::string sql = "insert into ";
            sql += Config::getInstance().userTableName();
            sql += " values(";
            std::string sep = "'";
            sql += sep + e.username + sep + ',';
            sql += sep + e.password + sep;
            sql += ')';
            bool ret = _mysql.query(sql);
            _shmux.unlock();
            return ret;
        }
        bool getOneByUsername(const std::string &name, UserNode *buffer)
        {
            bool ret = true;
            _shmux.lock_shared();
            if (!_table.count(name))
                ret = false;
            else
                *buffer = _table[name];
            _shmux.unlock_shared();
            return ret;
        }
        bool getAll(std::vector<UserNode> *array)
        {
            _shmux.lock_shared();

            for (auto e : _table)
            {
                array->push_back(e.second);
            }
            _shmux.unlock_shared();
            return true;
        }
        static UserManger &getInstance()
        {
            if (!_ptr)
            {
                std::unique_lock<std::mutex> locker(_mux);
                if (_ptr == nullptr)
                {
                    _ptr = new UserManger();
                }
            }
            return *_ptr;
        }

    private:
        UserManger()
        {
            std::string username=Config::getInstance().userName();
            std::string password=Config::getInstance().password();
            std::string database=Config::getInstance().database();
            std::string host=Config::getInstance().host();
            uint16_t port=Config::getInstance().port();
            _mysql.connect(username, password, database, host, port);
            std::string sql="create table if not exists ";
            sql+=Config::getInstance().userTableName()+" ";
            sql+="(username varchar(30) primary key,";
            sql+="password varchar(30) not null)";
            _mysql.query(sql);
            std::cout<<__FILE__<<": "<<__LINE__<<": "<<sql<<std::endl;
        }
        UserManger(const UserManger &);
        UserManger(const UserManger &&);

    private:
        static UserManger *_ptr;
        static std::mutex _mux;

    private:
        MysqlManger _mysql;
        std::shared_mutex _shmux;
        std::unordered_map<std::string, UserNode> _table;
    };
    UserManger *UserManger::_ptr = nullptr;
    std::mutex UserManger::_mux;

}